/**
 * OW2 FraSCAti Examples : HelloWorld POJO
 * Copyright (C) 2008-2010 INRIA, University of Lille 1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Haderer Nicolas
 *
 * Contributor(s): 
 */
package fr.univlille1.pji96.website;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.osoa.sca.annotations.Reference;
import org.osoa.sca.annotations.Scope;

import fr.univlille1.pji96.basex.api.IDatabase;

import net.sf.json.JSON;
import net.sf.json.xml.XMLSerializer;

@Scope("COMPOSITE")
public class WebSiteImpl implements IWebSite{

	@Reference(name="basex-database")
	private IDatabase db;
	
	public String getAllDatabase() {
		
		
		try {
			db.initSession("localhost", "1985", "admin", "admin");
			return db.commmand("LIST");
			
		} catch (Exception e) {
		
			e.printStackTrace();
			return e.getMessage();
		}
		finally{
			try {
				db.close();
				System.out.println("end session");
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}
	/**
	 * Retourn le contenu d'une requete dans un string
	 * @param nameQuery le nom du fichier de la requete xquery
	 * @return le contenu d'un fichier dans un string
	 * @throws IOException
	 */
	public String getFilInString(String nameQuery) throws IOException{
		String output = "";
		try {
			System.out.println("Ouverture du fichier : " + nameQuery);
			BufferedReader br = new BufferedReader(new FileReader("querys/" + nameQuery));
			String line = new String();
			while ((line = br.readLine()) != null){
				output += line;
			}
		} catch (Exception e) {
			System.out.println("Erreur d'ouvertur du fichier de la reqete");
			e.printStackTrace();
		}
		return output;
	}
	
	/***** Ajout d'une requette xquery 
	 * @throws IOException 
	 * @throws URISyntaxException 
	 * @throws FileNotFoundException ***********/
	public String addQuery(String nom, String point, String exp, String query, String options, List<String> badges) throws IOException{
		BufferedReader br;
		try {
			br = new BufferedReader(new FileReader("querys/add_query.xq"));
			
			String line = new String();
			String fichier = "";
			while ((line = br.readLine()) != null){
				System.out.println(line);
				fichier += line;
			}
			
			/******* Remplacement des valeurs dans la requête ************/
			fichier = fichier.replaceAll("!nom!", nom);
			fichier = fichier.replaceAll("!point!", point);
			fichier = fichier.replaceAll("!query!", query);
			fichier = fichier.replaceAll("!exp!", exp);
			if (options == "")
				fichier = fichier.replaceAll("!options!", "1=1");
			else
				fichier = fichier.replaceAll("!options!", options);
			
			/*** Badges **/
			boolean empty = false;
			String badgesString = "";
			int i = 0;
			if (!badges.isEmpty()){
				while(i<badges.size()-1){
					badgesString += "<badge>";
					if(badges.get(i).isEmpty()){
						empty = true;
						break;
					}
					badgesString += "<nom>"+badges.get(i) + "</nom>";
					badgesString += "<note>"+badges.get(i+1) + "</note>";
					i += 2;
					badgesString += "</badge>";
				}
			}
			if (empty)
				fichier = fichier.replaceAll("!badges!", "");
			else
				fichier = fichier.replaceAll("!badges!", badgesString);
			/*************************************************************/
			
			
			try{
				db.initSession("localhost", "1985", "admin", "admin");
				
				return db.query(fichier);
			} catch (Exception e) {
				
				e.printStackTrace();
				return e.getMessage();
			}
			finally{
				try {
					db.close();
					System.out.println("end session");
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return "";
		}
	}
	
	/**
	 * 
	 */
	public String calculeNotes() throws IOException{
		try {
			BufferedReader br = new BufferedReader(new FileReader("querys/calc_note_total.xq"));
			String line = new String();
			String fileCalcNotes = "";
			while ((line = br.readLine()) != null){
				fileCalcNotes += line;
			}
			
			// Date du jour
			String format = "yyyy-mm-dd";
			SimpleDateFormat formater = new SimpleDateFormat(format);
			Date date = new Date();
			
			// Rempplacement de la date du jour.
			fileCalcNotes = fileCalcNotes.replace("!date!", "2008-05-17");
			
			BufferedReader br2 = new BufferedReader(new FileReader("querys/transfert_results_base.xq"));
			
			String fileTransfert = "";
			while ((line = br2.readLine()) != null){
				fileTransfert += line;
			}
			
			try{
				db.initSession("localhost", "1985", "admin", "admin");
				
				/**** Suppression de la base results par précaution ******/
				db.query("let $db := doc('results') return delete node $db//xp");
				
				
				/*** Calcule des notes des utilisateurs **/
				db.query(fileCalcNotes);
				/**********************************/
				
				/*** Transfert des résultats dans la base xp ****/
				db.query(fileTransfert);
				/****************************/
				
				/**** Suppression de la base results ******/
				db.query("let $db := doc('results') return delete node $db//xp");
			} catch (Exception e) {
				
				e.printStackTrace();
				return e.getMessage();
			}
			finally{
				try {
					db.close();
					System.out.println("end session");
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	public String[] getExp(String email) throws IOException{
		String query = getFilInString("getExp.xq");
		query = query.replace("!email!", email);
		try{
			db.initSession("localhost", "1985", "admin", "admin");
			
			String ret = db.query(query);
			String[] xps = ret.split(" ");
			return xps;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		finally{
			try {
				db.close();
				System.out.println("end session");
				
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	/***
	 * Calcule la note globale de chaque utilisateur de la base xp
	 */
	public void calculeNoteGlobal() throws IOException{
		try {
			BufferedReader br = new BufferedReader(new FileReader("querys/getGlobalResults.xq"));
			String line = new String();
			String fileGetGlobal = "";
			while ((line = br.readLine()) != null){
				fileGetGlobal += line;
			}

			try {
				db.initSession("localhost", "1985", "admin", "admin");
				/**** Suppression de la table globalResults ******/
				db.query("let $db := doc('xp') return delete node ($db//globalResults/resultsByXp, $db//globalResults/resultsByInscription)");
				/*** Calcule des notes globales des utilisateurs par expérience **/
				db.query(fileGetGlobal);
				
				/*** Calcule du nombre de points par utilisateur cumulés grâce au inscriptions aux xps ***/
				String rqGetInscriptionResults = getFilInString("getInscriptionResults.xq");
				db.query(rqGetInscriptionResults);
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					db.close();
					System.out.println("end session");
					
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * Classe les utilisateur en fontion de l'expérience
	 */
	public void rankUsers() throws IOException{
		/*** Les requêtes de classement des utilisateurs par syst de notation et par xp ***/
		String rqDelNotationRanking = getFilInString("delNotationRanking.xq");
		String rqNotationRanking = getFilInString("NotationRanking.xq");
		String rqRankUser = getFilInString("rankUsers.xq");
		/**********************************************************************************/
		
		/*** Requêtes de notation par inscription aux expériences ****/
		String rqDelInscriptionRanking = getFilInString("delInscriptionRanking.xq");
		String rqInscriptionRanking = getFilInString("inscriptionRanking.xq");
		/***************************************************************/
		
		/*** Requêtes de global Ranking (Notation par expérience *****/
		String rqDelGlobalRanking = getFilInString("delGlobalRanking.xq");
		String rqGlobalRanking = getFilInString("getGlobalRanking.xq");
		/*************************************************************/
		
		try {
			db.initSession("localhost", "1985", "admin", "admin");
			System.out.println("Execution de la requete delNotationRanking.xq : ");
			db.query(rqDelNotationRanking);
			System.out.println("Execution de la requete NotationRanking.xq : ");
			db.query(rqNotationRanking);
			
			
			System.out.println("Execution de la rq : delInscriptionRanking.xq");
			db.query(rqDelInscriptionRanking);
			System.out.println("Execution de la rq : inscriptionRanking.xq");
			db.query(rqInscriptionRanking);
			
			System.out.println("Execution de la rq : delGlobalRanking.xq");
			db.query(rqDelGlobalRanking);
			System.out.println("Execution de la rq : globalRankin.xq");
			db.query(rqGlobalRanking);
			
			/*** Classement de tout les utilisateur avec tout les systême de notations ***/
			db.query(rqRankUser);
			/*****************************************************************************/
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				db.close();
				System.out.println("end session");
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	/**** Méthodes réservé aux fourmis *********/
	
	/**
	 * Donne le classement d'un utilisateur
	 * @throws IOException 
	 */
	public String getClassement(String user) throws IOException{
		String rqGetClassement = getFilInString("getClassementForUser.xq");
		rqGetClassement = rqGetClassement.replace("!user!", user);
		System.out.println(rqGetClassement);
		try {
			db.initSession("localhost", "1985", "admin", "admin");
			XMLSerializer xmlserializer = new XMLSerializer();
			String xml = db.query(rqGetClassement);
			System.out.println("XML Reçus : ");
			System.out.println(xml);
			JSON json = xmlserializer.read(xml);
			
			return json.toString(2);
			
		} catch (Exception e) {
			return null;
		}finally{
			try {
				db.close();
			} catch (Exception e2) {
				
			}
		}
	}
	
	public boolean findUser(String user, String pass) throws IOException{
		String rq = getFilInString("findUser.xq");
		String hashPass = getSha1(pass);
		
		rq = rq.replace("!email!", user);
		rq = rq.replace("!pass!", hashPass);
		try {
			db.initSession("localhost", "1985", "admin", "admin");
			Integer result = 0;
			result = Integer.parseInt(db.query(rq));
			if (result > 0)
				return true;
			else
				return false;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * Return le hash d'un mot de passe en SHA-1
	 */
	public String getSha1 (String pass){
		byte[] passByte = pass.getBytes();
		byte[] passSha1;
		try {
			passSha1 = MessageDigest.getInstance("SHA-1").digest(passByte);
		} catch (NoSuchAlgorithmException e) {
			throw new Error("no SHA-1 support in this VM");
		}
		StringBuffer hashString = new StringBuffer();
	    for ( int i = 0; i < passSha1.length; ++i ) { 
	    	String hex = Integer.toHexString(passSha1[i]); 
	        if ( hex.length() == 1 ) { 
	         hashString.append('0'); 
	         hashString.append(hex.charAt(hex.length()-1)); 
	        } else { 
	         hashString.append(hex.substring(hex.length()-2)); 
	        } 
	    }
	    return hashString.toString();
	}
	

}
